package com.leesk.trial.springbootdatastatistics.util;

import com.leesk.trial.springbootdatastatistics.pojo.Country;
import com.leesk.trial.springbootdatastatistics.pojo.Province;
import com.leesk.trial.springbootdatastatistics.pojo.RegionStats;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;
import org.springframework.core.io.Resource;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @Author: leesk
 * @Description:用于爬取疫情统计数据的csv文件以及做相应对比
 * @Date: Create in 9:13 2020/11/10
 */
public class CsvUtil {

    /**
     * @param url 爬取网页地址
     * @return
     * @Description:爬取url地址中的数据
     */
    public static InputStream fetchCoronaVirusData(String url) throws IOException {
        //  爬取全球新型冠状病毒统计数据的csv文件
        //  1. 实例化一个RequestEntity对象
        RequestEntity<Void> requestEntity = RequestEntity
                .get(URI.create(url))
                .headers(httpHeaders -> httpHeaders.add("User-Agent", "Mozilla/5.0"))
                .build();
        //  2. 通过RestTemplate的exchange方法获取csv文件
        ResponseEntity<Resource> exchange = new RestTemplate().exchange(requestEntity, Resource.class);
        //  3. 将csv文件中的数据会封装到一个Resource对象中
        Resource body = exchange.getBody();

        //  test：控制台输出爬取的csv文件数据
        System.out.println(body);

        //  4. 通过Resource对象的getInputStream方法获取csv文件的输入流
        InputStream inputStream = body.getInputStream();
//        byte[] a = new byte[1024];
//        while (inputStream.read(a) > 0){
//            System.out.println(new String(a));
//        }
        System.out.println();
        return inputStream;
    }

    /**
     * 对爬取到的数据进行处理
     *
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static List<RegionStats> getCoronaVirusData(InputStream inputStream) throws IOException {
        //  获取疫情数据的csv文件的输入流
        Reader input = new InputStreamReader(inputStream);
        //  用于保存每一条疫情数据
        List<RegionStats> statsList = new ArrayList<>();

        //  解析输入流，对疫情数据内容进行格式化，保存到容器中
        Iterable<CSVRecord> records = CSVFormat.DEFAULT
                .withFirstRecordAsHeader()  //  第一行设为标题
                .withRecordSeparator("\n")  //  每一行为一组数据
                .withDelimiter(',')         //  每一列以逗号为分隔
                .withQuote('"')             //  忽略双引号中的逗号
                .parse(input);

        //  遍历容器中的每一条数据，装入实体对象并添加到statsList中
        for (CSVRecord record : records) {
            String province = record.get(2);    // 获取省份/州
            String country = record.get(3);     //  获取国家/地区
            if (country.equals("Taiwan*")) {
                province = "台湾";
                country = "China";
            }
            String lastUpdateDate = record.get(4);  //  获取更新时间
            //int latest = Integer.parseInt(record.get(record.size() - 1));   //  获取最新累计新冠肺炎总数
            //int diff = Integer.parseInt(record.get(record.size() - 1)) - Integer.parseInt(record.get(record.size() - 2));   //  获取新增数量
            int confirmed = Integer.parseInt(record.get(7));   //  获取累计确诊数
            int deaths = Integer.parseInt(record.get(8));       //  获取累计死亡数
            int recovered = Integer.parseInt(record.get(9));    //  获取累计治愈数
            RegionStats rs = new RegionStats(province, country, lastUpdateDate, confirmed, deaths, recovered);
            statsList.add(rs);
        }

        //  排序
        Collections.sort(statsList);
        //  将中国的信息转化为中文
        TransferUtil.transferToChinese(statsList);
        //  打印加工后的数据
//        for (RegionStats r : statsList) {
//            System.out.println(r.getProvince() + " " + r.getCountry() + " " + r.getLastUpdateDate() + " " + r.getConfirmed() + " " + r.getDeaths() + " " + r.getRecovered());
//        }

        return statsList;
    }

    /**
     * 将获取到的数据分装到两个model里：Country和Province
     * @param regionStatsList
     * @return
     */
    public static List<Country> addProvinceAndCountry(List<RegionStats> regionStatsList) {
        List<Country> countryList = new ArrayList<>();

        for (int i = 0; i < regionStatsList.size(); i++) {
            RegionStats regionStats = regionStatsList.get(i);
            String countryName = regionStats.getCountry();
            String provinceName = regionStats.getProvince();
            int provinceConfirmed = regionStats.getConfirmed();
            int provinceDeaths = regionStats.getDeaths();
            int provinceRecovered = regionStats.getRecovered();
            //  如果没有省份或州的话，那就是一个地区，直接添加到countryList
            if(provinceName.equals("")){
                Country country = new Country(countryName,provinceConfirmed,provinceDeaths,provinceRecovered,null);
                countryList.add(country);
            }else { //  否则为某个国家的一个省份或州
                List<Province> provinceList = new ArrayList<>();
                int countryConfirmed = provinceConfirmed;
                int countryDeaths = provinceDeaths;
                int countryRecovered = provinceRecovered;
                while (true){
                    provinceList.add(new Province(provinceName, provinceConfirmed,provinceDeaths,provinceRecovered));
                    i++;
                    regionStats = regionStatsList.get(i);
                    String checkCountry = regionStats.getCountry();
                    provinceName = regionStats.getProvince();
                    provinceConfirmed = regionStats.getConfirmed();
                    provinceDeaths = regionStats.getDeaths();
                    provinceRecovered = regionStats.getRecovered();
                    //  如果遍历到下一个国家或地区则退出
                    if(!checkCountry.equals(countryName)){
                        i--;
                        break;
                    }
                    countryConfirmed += provinceConfirmed;
                    countryDeaths += provinceDeaths;
                    countryRecovered += provinceRecovered;
                }
                Country country = new Country(countryName, countryConfirmed, countryDeaths, countryRecovered, provinceList);
                countryList.add(country);
            }
        }
        Collections.sort(countryList);
        return countryList;
    }
}
